import os from 'os';
import { exec } from 'node:child_process';
import { run } from './shell';
import log from 'electron-log/node';

const PLATFORM = os.platform();
const SUPPORTED_PLATFORMS = ['win32', 'darwin', 'linux'];

/**
 * 检查端口是否被占用
 */
async function isPortOccupied(port: number): Promise<boolean> {
  if (!SUPPORTED_PLATFORMS.includes(PLATFORM)) {
    console.warn(`Unsupported platform: ${PLATFORM}`);
    return false;
  }

  try {
    if (PLATFORM === 'win32') {
      const { stdout } = await run(`netstat -ano`);
      return new RegExp(`:${port}\\s+LISTENING`, 'i').test(stdout);
    } else {
      const { stdout } = await run(`lsof -i:${port}`);
      return !!stdout.trim();
    }
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    console.warn(`Error running isPortOccupied: ${message}`);
    return false;
  }
}

/**
 * 杀死占用指定端口的进程
 */
async function killProcessUsingPort(port: number): Promise<boolean> {
  try {
    let pids: string[] = [];

    if (PLATFORM === 'win32') {
      const { stdout } = await run(`netstat -ano`);
      const regex = new RegExp(`:${port}.*LISTENING\\s+(\\d+)`, 'i');
      stdout.split('\n').forEach((line) => {
        const match = line.match(regex);
        if (match) pids.push(match[1]);
      });
    } else {
      const { stdout } = await run(`lsof -t -i:${port}`);
      if (stdout) pids = stdout.trim().split('\n');
    }

    if (!pids.length) {
      console.log(`No process found using port ${port}`);
      return true;
    }

    let allSucceeded = true;
    for (const pid of pids) {
      try {
        if (PLATFORM === 'win32') {
          await run(`taskkill /F /PID ${pid}`);
        } else {
          await run(`kill -15 ${pid}`); // graceful shutdown
        }
        console.log(`Killed process ${pid} using port ${port}`);
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        console.error(`Failed to kill process ${pid}:`, message);
        allSucceeded = false;
      }
    }

    return allSucceeded;
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    console.error(`Error checking port ${port}:`, message);
    return false;
  }
}

/**
 * 确保端口可用
 */
export async function ensurePortAvailable(port: number): Promise<boolean> {
  try {
    if (await isPortOccupied(port)) {
      console.log(`Port ${port} is occupied, attempting to kill...`);
      const killResult = await killProcessUsingPort(port);

      if (!killResult || (await isPortOccupied(port))) {
        console.error(`Failed to free port ${port}`);
        return false;
      }
    }
    console.log(`Port ${port} is available`);
    return true;
  } catch (error) {
    console.error(`Error processing port ${port}:`, (error as Error).message);
    return false;
  }
}

/**
 * 根据进程 ID 杀死指定进程及其子进程的辅助函数
 *
 * 根据操作系统平台使用不同的方法：
 * - Windows: 使用 taskkill 命令（/T 表示终止子进程，/F 表示强制终止）
 * - Unix/MacOS: 使用 process.kill 方法（发送 SIGTERM 信号）
 *
 * @param {number} pid - 要终止的进程 ID
 * @returns {Promise<void>} 表示进程终止操作的 Promise
 */
export function killProcess(pid: number): Promise<void> {
  return new Promise((resolve, reject) => {
    if (process.platform === 'win32') {
      // Windows 平台使用 taskkill 命令杀死进程
      exec(`taskkill /PID ${pid} /T /F`, (error, stdout, stderr) => {
        if (error) {
          log.error(`杀死 Python 进程时出错: ${stderr}`);
          reject(error);
        } else {
          log.info(`Python 进程 ${pid} 及其子进程已终止`);
          resolve();
        }
      });
    } else {
      try {
        // Unix 平台使用 kill 命令
        // 负号表示杀死进程组（主进程及其子进程）
        process.kill(-pid, 'SIGTERM');
        log.info(`Python 进程 ${pid} 及其子进程已终止`);
        resolve();
      } catch (err) {
        log.error(`无法杀死 Python 进程: ${err}`);
        reject(err);
      }
    }
  });
}

export function killProcessAll(pid: number): Promise<void> {
  return new Promise((resolve, reject) => {
    if (process.platform === 'win32') {
      // Windows平台使用tasklist获取子进程PID
      exec(`tasklist /fi "PID eq ${pid}" /fo csv`, (error, stdout, stderr) => {
        if (error) {
          log.error(`获取进程信息时出错: ${stderr}`);
          reject(error);
        } else {
          const processList = stdout.split('\n');
          processList.forEach((line) => {
            const parts = line.split('","');
            if (parts[1] && parts[1] !== pid.toString()) {
              // 查找到子进程并尝试杀死
              const childPid = parts[1].replace(/"/g, '');
              exec(
                `taskkill /PID ${childPid} /F`,
                (killError, killStdout, killStderr) => {
                  if (killError) {
                    log.error(`无法杀死子进程 ${childPid}: ${killStderr}`);
                  } else {
                    log.info(`子进程 ${childPid} 已终止`);
                  }
                }
              );
            }
          });
          // 然后杀死主进程
          exec(
            `taskkill /PID ${pid} /F`,
            (killError, killStdout, killStderr) => {
              if (killError) {
                log.error(`无法杀死主进程 ${pid}: ${killStderr}`);
                reject(killError);
              } else {
                log.info(`主进程 ${pid} 已终止`);
                resolve();
              }
            }
          );
        }
      });
    } else {
      try {
        // Unix平台使用kill命令，终止进程组
        process.kill(-pid, 'SIGTERM');
        log.info(`Python 进程 ${pid} 及其子进程已终止`);
        resolve();
      } catch (err) {
        log.error(`无法杀死 Python 进程: ${err}`);
        reject(err);
      }
    }
  });
}
